#include <iostream>
#include <fstream>
#include <unistd.h>
#include "parser/parser.h"
#include "compiler/compiler.h"
using namespace std;

// map<string,type> type_table;
// map<string,variable_info> variable_table;
// map<string,function_info> function_table;
// map<string,class_info> class_table;
// 类--类中的成员变量
// 类--类中的成员函数
// 类--类成员函数中的变量

void help(){
    printf("用法: pandac 参数 文件 [第三方库路径]\n");
    printf("\t单独进行编译过程的某一阶段\n");
    printf("\t参数选项：\n");
    printf("\t-p   对文件进行预处理(处理import语句)\n");
    printf("\t-l   对文件进行词法分析\n");
    printf("\t-s   对文件进行语法法分析\n");
    printf("\t-g1  对token序列进行第一遍扫描，获取并检查类型信息\n");
    printf("\t-g2  对token序列进行第二遍扫描，获取并检查成员函数信息\n");
    printf("\t-g3  对token序列进行第三遍扫描，获取抽象语法树\n");
    printf("\t-c   代码生成，将源代码编译成汇编代码\n\n");

    
    printf("用法: pandac 文件 [第三方库路径]\n");
    printf("\t执行编译过程的所有阶段\n\n");

    printf("用法: pandac -h \n");
    printf("\t显示此帮助信息并退出\n");
}




int main(int argc, char **argv)
{

    if (argc < 2 || argc > 4){
        printf("无法解析的参数格式,使用方式如下\n\n");
        help();
        return 0;
    }
    else{
        compiler compiler;
        string param = argv[1];
        string packagePath;
        string packageName;

        if (param == "-p"){
                sleep(1);
                printf("正在进行预处理...\n");
                packageName = argv[2];
                packagePath = argc == 4 ? argv[3] : "";
                if (compiler.import(packagePath,packageName) == false){
                    sleep(1);
                    printf("预处理过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("预处理完成,已生成临时文件%s\n",TEMP_FILE_NAME);
                sleep(1);
                
                remove(TOKEN_SEQUENCE);
                remove(DATAMEMBER_INFO);
                remove(FUNCMEMBER_INFO);
                remove(GRAMMAR_TREE);
                remove(ASSEMBLE_FILE);
                return 0;
        }
        else if (param == "-l"){
                packageName = argv[2];
                packagePath = argc == 4 ? argv[3] : "";
                if (compiler.import(packagePath,packageName) == false){
                    sleep(1);
                    printf("预处理过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                
                
                sleep(1);
                printf("正在进行词法分析...\n");
                if (compiler.lexicalAnalysis() == false){
                    sleep(1);
                    printf("词法分析过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("词法分析完成,已将token序列写入文件%s\n",TOKEN_SEQUENCE);
                sleep(1);


                remove(TEMP_FILE_NAME);

                remove(DATAMEMBER_INFO);
                remove(FUNCMEMBER_INFO);
                remove(GRAMMAR_TREE);
                remove(ASSEMBLE_FILE);
                return 0;
                
        }
        else if (param == "-s"){
                packageName = argv[2];
                packagePath = argc == 4 ? argv[3] : "";
                if (compiler.import(packagePath,packageName) == false){
                    sleep(1);
                    printf("预处理过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                if (compiler.lexicalAnalysis() == false){
                    sleep(1);
                    printf("词法分析过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                sleep(1);
                printf("正在进行语法分析...\n");
                tokens.resetIndex();
                compiler.parser.updateNumberOfParsingTimes();
                compiler.parser.parse();
                sleep(1);
                printf("语法分析完成\n");
                sleep(1);

                remove(TEMP_FILE_NAME);
                remove(TOKEN_SEQUENCE);
                remove(DATAMEMBER_INFO);
                remove(FUNCMEMBER_INFO);
                remove(GRAMMAR_TREE);
                remove(ASSEMBLE_FILE);
                return 0;
        }
        else if (param == "-g1"){
                packageName = argv[2];
                packagePath = argc == 4 ? argv[3] : "";
                if (compiler.import(packagePath,packageName) == false){
                    sleep(1);
                    printf("预处理过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                if (compiler.lexicalAnalysis() == false){
                    sleep(1);
                    printf("词法分析过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                sleep(1);
                printf("正在收集类型信息...\n");
                if (compiler.grammaticalAnalysis_1() == false){
                    sleep(1);
                    printf("收集类型信息过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("类型信息收集完成,已将类型信息写入文件%s\n",DATAMEMBER_INFO);
                sleep(1);

                remove(TEMP_FILE_NAME);
                remove(TOKEN_SEQUENCE);

                remove(FUNCMEMBER_INFO);
                remove(GRAMMAR_TREE);
                remove(ASSEMBLE_FILE);
                return 0;
                
        }
        else if (param == "-g2"){
                packageName = argv[2];
                packagePath = argc == 4 ? argv[3] : "";
                if (compiler.import(packagePath,packageName) == false){
                    sleep(1);
                    printf("预处理过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                

                if (compiler.lexicalAnalysis() == false){
                    sleep(1);
                    printf("词法分析过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                

                if (compiler.grammaticalAnalysis_1() == false){
                    sleep(1);
                    printf("收集类型信息过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                
                sleep(1);
                printf("正在收集成员函数信息...\n");
                if (compiler.grammaticalAnalysis_2() == false){
                    sleep(1);
                    printf("收集成员函数信息过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("成员函数信息收集完成,已将成员函数信息写入文件%s\n",FUNCMEMBER_INFO);
                sleep(1);
                remove(TEMP_FILE_NAME);
                remove(TOKEN_SEQUENCE);
                remove(DATAMEMBER_INFO);

                remove(GRAMMAR_TREE);
                remove(ASSEMBLE_FILE);
                return 0;
        }
        else if (param == "-g3"){
                packageName = argv[2];
                packagePath = argc == 4 ? argv[3] : "";
                if (compiler.import(packagePath,packageName) == false){
                    sleep(1);
                    printf("预处理过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                
                if (compiler.lexicalAnalysis() == false){
                    sleep(1);
                    printf("词法分析过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                

                if (compiler.grammaticalAnalysis_1() == false){
                    sleep(1);
                    printf("收集类型信息过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                
                if (compiler.grammaticalAnalysis_2() == false){
                    sleep(1);
                    printf("收集成员函数信息过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }

                
                sleep(1);
                printf("正在生成抽象语法树...\n");
                if (compiler.grammaticalAnalysis_3() == false){
                    sleep(1);
                    printf("生成抽象语法树过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("成功生成抽象语法树，已将抽象语法树写入文件%s\n",GRAMMAR_TREE);
                sleep(1);
                
                remove(TEMP_FILE_NAME);
                remove(TOKEN_SEQUENCE);
                remove(DATAMEMBER_INFO);
                remove(FUNCMEMBER_INFO);

                remove(ASSEMBLE_FILE);
                return 0;
        }
        else if (param == "-c"){
                packageName = argv[2];
                packagePath = argc == 4 ? argv[3] : "";
                if (compiler.import(packagePath,packageName) == false){
                    sleep(1);
                    printf("预处理过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                

                if (compiler.lexicalAnalysis() == false){
                    sleep(1);
                    printf("词法分析过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                

                if (compiler.grammaticalAnalysis_1() == false){
                    sleep(1);
                    printf("收集类型信息过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }


                

                if (compiler.grammaticalAnalysis_2() == false){
                    sleep(1);
                    printf("收集成员函数信息过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }

                
                

                if (compiler.grammaticalAnalysis_3() == false){
                    sleep(1);
                    printf("生成抽象语法树过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }

                
                
                sleep(1);
                printf("正在编译成汇编...\n");
                compiler.compile();
                sleep(1);
                printf("编译完成，已将汇编语句写入文件%s\n",ASSEMBLE_FILE);

                remove(TEMP_FILE_NAME);
                remove(TOKEN_SEQUENCE);
                remove(DATAMEMBER_INFO);
                remove(FUNCMEMBER_INFO);
                remove(GRAMMAR_TREE);

                return 0;
        }
        else if (param == "-h"){
            help();
            
        }
        else {
            if (argc > 3){
                printf("无法解析的参数格式,使用方式如下\n\n");
                help();
            }
            else{
                packageName = argv[1];
                packagePath = argc == 3 ? argv[2] : "";
                sleep(1);
                printf("正在进行预处理...\n");
                if (compiler.import(packagePath,packageName) == false){
                    sleep(1);
                    printf("预处理过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("预处理完成,已生成临时文件%s\n",TEMP_FILE_NAME);
                

                sleep(1);
                printf("正在进行词法分析...\n");
                if (compiler.lexicalAnalysis() == false){
                    sleep(1);
                    printf("词法分析过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("词法分析完成,已将token序列写入文件%s\n",TOKEN_SEQUENCE);
                
                sleep(1);
                printf("正在收集类型信息...\n");
                // 加个正在进行类型检查的信息
                if (compiler.grammaticalAnalysis_1() == false){
                    sleep(1);
                    printf("收集类型信息过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("类型信息收集完成,已将类型信息写入文件%s\n",DATAMEMBER_INFO);
                
                sleep(1);
                printf("正在收集成员函数信息...\n");
                if (compiler.grammaticalAnalysis_2() == false){
                    sleep(1);
                    printf("收集成员函数信息过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("成员函数信息收集完成,已将成员函数信息写入文件%s\n",FUNCMEMBER_INFO);
                
                sleep(1);
                printf("正在生成抽象语法树...\n");
                if (compiler.grammaticalAnalysis_3() == false){
                    sleep(1);
                    printf("生成抽象语法树过程中发生了错误,编译程序将退出!\n");
                    goto EXIT;
                }
                sleep(1);
                printf("成功生成抽象语法树，已将抽象语法树写入文件%s\n",GRAMMAR_TREE);
                
                sleep(1);
                printf("正在编译成汇编...\n");
                compiler.compile();
                sleep(1);
                printf("编译完成，已将汇编语句写入文件%s\n",ASSEMBLE_FILE);
                sleep(1);
                return 0;
            }
        }
    }

    EXIT:
        remove(TEMP_FILE_NAME);
        remove(TOKEN_SEQUENCE);
        remove(DATAMEMBER_INFO);
        remove(FUNCMEMBER_INFO);
        remove(GRAMMAR_TREE);
        remove(ASSEMBLE_FILE);
    
    return 0;
}